#ifndef STATEENGINE_H_
#define STATEENGINE_H_

#include "scHeader.h"
#include <QObject>

namespace sybilpm
{

/**
 * A generic state engine with no context binding.
 */
class StateEngine : public QObject
{
	Q_OBJECT
signals:
	void stateChangeSig(int newState);
	void stateRenewSig(int state);
protected:
	typedef std::map<int, std::string> States;
	typedef std::multimap<int, std::pair<int, int> > Transis; // source -> (target, transi ID)
public:
	StateEngine();
	virtual ~StateEngine();
	/* returns the state ID */
	virtual int addState(std::string stateName);
	/* returns the transition ID */
	virtual int addTransition(int sourceState, int targetState);
	/* returns the current state ID */
	virtual int getState() const {return state;}
	/* returns the current state text */
	virtual const std::string & getStateText() const {return states.find(state)->second;}
	/* get a textual representation of the object */
	virtual std::string toString() const;
	/**
	 * Goes from current state to targetState and returns
	 * the transition ID. Throws an AppExecption if there
	 * is no such transition.
	 */
	virtual int makeTransition(int targetState);
	/**
	 * tries to go from current state to targetState if there
	 * is such a transition. Returns the transition ID if
	 * possible or -1 if no transition was made.
	 */
	virtual int tryTransition(int targetState);
	/**
	 * Same as tryTransition but does not execute the transition.
	 */
	virtual int testTransition(int targetState) const;

protected:
	States states;
	Transis transis;
	int numStates;
	int numTransi;
	int state;
};

} // namespace sybilpm

namespace std
{
ostream & operator<<(ostream & out, const sybilpm::StateEngine & data);
}

#endif /* STATEENGINE_H_ */
